﻿using System.Linq.Expressions;
using BootstrapBlazor.Components;
using BPM.Web.Shared.Data;
using Omu.ValueInjecter;
using Omu.ValueInjecter.Injections;

namespace BPM.Web.Shared.Extensions;

public static class ObjectExtensions
{

    /// <summary>
    /// 转换成目标对象
    /// </summary>
    /// <typeparam name="TResult">目标对象</typeparam>
    /// <param name="input">要转换的对象</param>
    /// <returns></returns>
    public static TResult Adapt<TResult>(this BaseVM input) where TResult : BaseVM, new()
        => (input == null) ? new() : Mapper.Map<TResult>(input);

    /// <summary>
    /// 转换成目标对象
    /// </summary>
    /// <typeparam name="TResult">目标对象</typeparam>
    /// <param name="input">要转换的对象</param>
    /// <returns></returns>
    public static TResult Adapt<TResult>(this BaseVM input, QueryPageOptions? options)
        where TResult : PageInputBase, new()
    {
        var result = (input == null) ? new() : Mapper.Map<TResult>(input);
        if (options != null)
        {
            result.PageNo = options.PageIndex;
            result.PageSize = options.PageItems;
            if (!string.IsNullOrWhiteSpace(options.SearchText))
            {
                result.SearchValue = options.SearchText;
            }
        }
        return result;
    }

    /// <summary>
    /// 拷贝目标对象值
    /// </summary>
    /// <param name="input">赋值对象</param>
    /// <param name="source">要拷贝的数据源</param>
    /// <param name="ignoredProps">忽略的属性</param>
    /// <returns></returns>
    public static void Assign(this BaseVM? input, object? source, string[]? ignoredProps = null)
    {
        //赋值对象为空手时，不处理
        if (input == null)
        {
            return;
        }
        if (source != null)
        {
            input.InjectFrom(new LoopInjection(ignoredProps ?? Array.Empty<string>()), source);
        }
    }

    /// <summary>
    /// 更新属性值
    /// </summary>
    /// <typeparam name="TItem"></typeparam>
    /// <typeparam name="TValue"></typeparam>
    /// <param name="data"></param>
    /// <param name="expression"></param>
    /// <param name="value"></param>
    public static TItem SetValue<TItem, TValue>(this TItem data, Expression<Func<TItem, TValue>> expression, TValue value)
    {
        var member = expression.Body as MemberExpression
            ?? (MemberExpression)((UnaryExpression)expression.Body).Operand;
        var body = Expression.Assign(member, Expression.Constant(value));
        var lambda = Expression.Lambda<Action<TItem>>(body, expression.Parameters);
        lambda.Compile().Invoke(data);
        return data;
    }

    /// <summary>
    /// 转换为Task
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static Task<TValue> AsTask<TValue>(this TValue value)
        => Task.FromResult(value);
}

